<template>
  <view :class="'interlayer ' + (c || '')" :style="s">
    <block v-for="(n, i) in nodes" v-bind:key="i">
      <!--图片-->
      <view
        v-if="n.name == 'img'"
        :class="'_img ' + n.attrs.class"
        :style="n.attrs.style"
        :data-attrs="n.attrs"
        @tap.stop="imgtap"
      >
        <rich-text
          v-if="ctrl[i] != 0"
          :nodes="[
            {
              attrs: {
                src:
                  loading && (ctrl[i] || 0) < 2
                    ? loading
                    : lazyLoad && !ctrl[i]
                    ? placeholder
                    : ctrl[i] == 3
                    ? errorImg
                    : n.attrs.src || '',
                alt: n.attrs.alt || '',
                width: n.attrs.width || '',
                style:
                  '-webkit-touch-callout:none;max-width:100%;display:block' +
                  (n.attrs.height ? ';height:' + n.attrs.height : ''),
              },
              name: 'img',
            },
          ]"
        />
        <image
          class="_image"
          :src="lazyLoad && !ctrl[i] ? placeholder : n.attrs.src"
          :lazy-load="lazyLoad"
          :show-menu-by-longpress="!n.attrs.ignore"
          :data-i="i"
          :data-index="n.attrs.i"
          data-source="img"
          @load="loadImg"
          @error="error"
        />
      </view>
      <!--文本-->
      <text v-else-if="n.type == 'text'" decode>{{ n.text }}</text>
      <!--#ifndef MP-BAIDU-->
      <text v-else-if="n.name == 'br'">\n</text>
      <!--#endif-->
      <!--视频-->
      <view
        v-else-if="
          ((n.lazyLoad && !n.attrs.autoplay) ||
            (n.name == 'video' && !loadVideo)) &&
          ctrl[i] == undefined
        "
        :id="n.attrs.id"
        :class="'_video ' + (n.attrs.class || '')"
        :style="n.attrs.style"
        :data-i="i"
        @tap.stop="_loadVideo"
      />
      <video
        v-else-if="n.name == 'video'"
        :id="n.attrs.id"
        :class="n.attrs.class"
        :style="n.attrs.style"
        :autoplay="n.attrs.autoplay || ctrl[i] == 0"
        :controls="n.attrs.controls"
        :loop="n.attrs.loop"
        :muted="n.attrs.muted"
        :poster="n.attrs.poster"
        :src="n.attrs.source[ctrl[i] || 0]"
        :unit-id="n.attrs['unit-id']"
        :data-id="n.attrs.id"
        :data-i="i"
        data-source="video"
        @error="error"
        @play="play"
      />
      <!--音频-->
      <audio
        v-else-if="n.name == 'audio'"
        :ref="n.attrs.id"
        :class="n.attrs.class"
        :style="n.attrs.style"
        :author="n.attrs.author"
        :autoplay="n.attrs.autoplay"
        :controls="n.attrs.controls"
        :loop="n.attrs.loop"
        :name="n.attrs.name"
        :poster="n.attrs.poster"
        :src="n.attrs.source[ctrl[i] || 0]"
        :data-i="i"
        :data-id="n.attrs.id"
        data-source="audio"
        @error.native="error"
        @play.native="play"
      />
      <!--链接-->
      <view
        v-else-if="n.name == 'a'"
        :id="n.attrs.id"
        :class="'_a ' + (n.attrs.class || '')"
        hover-class="_hover"
        :style="n.attrs.style"
        :data-attrs="n.attrs"
        @tap.stop="linkpress"
      >
        <trees class="_span" c="_span" :nodes="n.children" />
      </view>
      <!--广告-->
      <!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :unit-id="n.attrs['unit-id']" :appid="n.attrs.appid" :apid="n.attrs.apid" :type="n.attrs.type" :adpid="n.attrs.adpid" data-source="ad" @error="error" />-->
      <!--列表-->
      <view
        v-else-if="n.name == 'li'"
        :id="n.attrs.id"
        :class="n.attrs.class"
        :style="(n.attrs.style || '') + ';display:flex;flex-direction:row'"
      >
        <view v-if="n.type == 'ol'" class="_ol-bef">{{ n.num }}</view>
        <view v-else class="_ul-bef">
          <view v-if="n.floor % 3 == 0" class="_ul-p1">█</view>
          <view v-else-if="n.floor % 3 == 2" class="_ul-p2" />
          <view v-else class="_ul-p1" style="border-radius: 50%">█</view>
        </view>
        <trees
          class="_li"
          c="_li"
          :nodes="n.children"
          :lazyLoad="lazyLoad"
          :loading="loading"
        />
      </view>
      <!--表格-->
      <view
        v-else-if="n.name == 'table' && n.c && n.flag"
        :id="n.attrs.id"
        :class="n.attrs.class"
        :style="(n.attrs.style || '') + ';display:grid'"
      >
        <trees
          v-for="(cell, n) in n.children"
          v-bind:key="n"
          :class="cell.attrs.class"
          :c="cell.attrs.class"
          :style="cell.attrs.style"
          :s="cell.attrs.style"
          :nodes="cell.children"
        />
      </view>
      <view
        v-else-if="n.name == 'table' && n.c"
        :id="n.attrs.id"
        :class="n.attrs.class"
        :style="(n.attrs.style || '') + ';display:table'"
      >
        <view
          v-for="(tbody, o) in n.children"
          v-bind:key="o"
          :class="tbody.attrs.class"
          :style="
            (tbody.attrs.style || '') +
            (tbody.name[0] == 't'
              ? ';display:table-' + (tbody.name == 'tr' ? 'row' : 'row-group')
              : '')
          "
        >
          <view
            v-for="(tr, p) in tbody.children"
            v-bind:key="p"
            :class="tr.attrs.class"
            :style="
              (tr.attrs.style || '') +
              (tr.name[0] == 't'
                ? ';display:table-' + (tr.name == 'tr' ? 'row' : 'cell')
                : '')
            "
          >
            <trees v-if="tr.name == 'td'" :nodes="tr.children" />
            <trees
              v-else
              v-for="(td, q) in tr.children"
              v-bind:key="q"
              :class="td.attrs.class"
              :c="td.attrs.class"
              :style="
                (td.attrs.style || '') +
                (td.name[0] == 't'
                  ? ';display:table-' + (td.name == 'tr' ? 'row' : 'cell')
                  : '')
              "
              :s="
                (td.attrs.style || '') +
                (td.name[0] == 't'
                  ? ';display:table-' + (td.name == 'tr' ? 'row' : 'cell')
                  : '')
              "
              :nodes="td.children"
            />
          </view>
        </view>
      </view>
      <!--#ifdef APP-PLUS-->
      <iframe
        v-else-if="n.name == 'iframe'"
        :style="n.attrs.style"
        :allowfullscreen="n.attrs.allowfullscreen"
        :frameborder="n.attrs.frameborder"
        :width="n.attrs.width"
        :height="n.attrs.height"
        :src="n.attrs.src"
      />
      <embed
        v-else-if="n.name == 'embed'"
        :style="n.attrs.style"
        :width="n.attrs.width"
        :height="n.attrs.height"
        :src="n.attrs.src"
      />
      <!--#endif-->
      <!--富文本-->
      <!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
      <rich-text
        v-else-if="handler.use(n)"
        :id="n.attrs.id"
        :class="'_p __' + n.name"
        :nodes="[n]"
      />
      <!--#endif-->
      <!--#ifndef MP-WEIXIN || MP-QQ || APP-PLUS-->
      <rich-text
        v-else-if="!n.c"
        :id="n.attrs.id"
        :nodes="[n]"
        style="display: inline"
      />
      <!--#endif-->
      <trees
        v-else
        :class="
          (n.attrs.id || '') + ' _' + n.name + ' ' + (n.attrs.class || '')
        "
        :c="(n.attrs.id || '') + ' _' + n.name + ' ' + (n.attrs.class || '')"
        :style="n.attrs.style"
        :s="n.attrs.style"
        :nodes="n.children"
        :lazyLoad="lazyLoad"
        :loading="loading"
      />
    </block>
  </view>
</template>
<script module="handler" lang="wxs" src="./handler.wxs"></script>
<script>
global.Parser = {};
import trees from "./trees";
import config from "./config.js";
const errorImg = config.errorImg;
export default {
  components: {
    trees,
  },
  name: "trees",
  data() {
    return {
      ctrl: [],
      placeholder:
        'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="225"/>',
      errorImg,
      loadVideo: typeof plus == "undefined",
      // #ifndef MP-ALIPAY
      c: "",
      s: "",
      // #endif
    };
  },
  props: {
    nodes: Array,
    lazyLoad: Boolean,
    loading: String,
    // #ifdef MP-ALIPAY
    c: String,
    s: String,
    // #endif
  },
  mounted() {
    for (
      this.top = this.$parent;
      this.top.$options.name != "jyf-parser";
      this.top = this.top.$parent
    );
    this.init();
  },
  // #ifdef APP-PLUS
  beforeDestroy() {
    this.observer && this.observer.disconnect();
  },
  // #endif
  methods: {
    init() {
      for (var i = this.nodes.length, n; (n = this.nodes[--i]); ) {
        if (n.name == "img") {
          this.top.imgList.setItem(
            n.attrs.i,
            n.attrs["original-src"] || n.attrs.src
          );
          // #ifdef APP-PLUS
          if (this.lazyLoad && !this.observer) {
            this.observer = uni
              .createIntersectionObserver(this)
              .relativeToViewport({
                top: 500,
                bottom: 500,
              });
            setTimeout(() => {
              this.observer.observe("._img", (res) => {
                if (res.intersectionRatio) {
                  for (var j = this.nodes.length; j--; )
                    if (this.nodes[j].name == "img") this.$set(this.ctrl, j, 1);
                  this.observer.disconnect();
                }
              });
            }, 0);
          }
          // #endif
        } else if (n.name == "video" || n.name == "audio") {
          var ctx;
          if (n.name == "video") {
            ctx = uni.createVideoContext(
              n.attrs.id,
              // #ifndef MP-BAIDU
              this
              // #endif
            );
          } else if (this.$refs[n.attrs.id]) ctx = this.$refs[n.attrs.id][0];
          if (ctx) {
            ctx.id = n.attrs.id;
            this.top.videoContexts.push(ctx);
          }
        }
      }
      // #ifdef APP-PLUS
      // APP 上避免 video 错位需要延时渲染
      setTimeout(() => {
        this.loadVideo = true;
      }, 1000);
      // #endif
    },
    play(e) {
      var contexts = this.top.videoContexts;
      if (contexts.length > 1 && this.top.autopause)
        for (var i = contexts.length; i--; )
          if (contexts[i].id != e.currentTarget.dataset.id) contexts[i].pause();
    },
    imgtap(e) {
      var attrs = e.currentTarget.dataset.attrs;
      if (!attrs.ignore) {
        var preview = true,
          data = {
            id: e.target.id,
            src: attrs.src,
            ignore: () => (preview = false),
          };
        global.Parser.onImgtap && global.Parser.onImgtap(data);
        this.top.$emit("imgtap", data);
        if (preview) {
          var urls = this.top.imgList,
            current = urls[attrs.i]
              ? parseInt(attrs.i)
              : ((urls = [attrs.src]), 0);
          uni.previewImage({
            current,
            urls,
          });
        }
      }
    },
    loadImg(e) {
      var i = e.currentTarget.dataset.i;
      if (this.lazyLoad && !this.ctrl[i]) {
        // #ifdef QUICKAPP-WEBVIEW
        this.$set(this.ctrl, i, 0);
        this.$nextTick(function () {
          // #endif
          // #ifndef APP-PLUS
          this.$set(this.ctrl, i, 1);
          // #endif
          // #ifdef QUICKAPP-WEBVIEW
        });
        // #endif
      } else if (this.loading && this.ctrl[i] != 2) {
        // #ifdef QUICKAPP-WEBVIEW
        this.$set(this.ctrl, i, 0);
        this.$nextTick(function () {
          // #endif
          this.$set(this.ctrl, i, 2);
          // #ifdef QUICKAPP-WEBVIEW
        });
        // #endif
      }
    },
    linkpress(e) {
      var jump = true,
        attrs = e.currentTarget.dataset.attrs;
      attrs.ignore = () => (jump = false);
      global.Parser.onLinkpress && global.Parser.onLinkpress(attrs);
      this.top.$emit("linkpress", attrs);
      if (jump) {
        // #ifdef MP
        if (attrs["app-id"]) {
          return uni.navigateToMiniProgram({
            appId: attrs["app-id"],
            path: attrs.path,
          });
        }
        // #endif
        if (attrs.href) {
          if (attrs.href[0] == "#") {
            if (this.top.useAnchor)
              this.top.navigateTo({
                id: attrs.href.substring(1),
              });
          } else if (
            attrs.href.indexOf("http") == 0 ||
            attrs.href.indexOf("//") == 0
          ) {
            // #ifdef APP-PLUS
            plus.runtime.openWeb(attrs.href);
            // #endif
            // #ifndef APP-PLUS
            uni.setClipboardData({
              data: attrs.href,
              success: () =>
                uni.showToast({
                  title: "链接已复制",
                }),
            });
            // #endif
          } else
            uni.navigateTo({
              url: attrs.href,
              fail() {
                uni.switchTab({
                  url: attrs.href,
                });
              },
            });
        }
      }
    },
    error(e) {
      var target = e.currentTarget,
        source = target.dataset.source,
        i = target.dataset.i;
      if (source == "video" || source == "audio") {
        // 加载其他 source
        var index = this.ctrl[i] ? this.ctrl[i].i + 1 : 1;
        if (index < this.nodes[i].attrs.source.length)
          this.$set(this.ctrl, i, index);
        if (e.detail.__args__) e.detail = e.detail.__args__[0];
      } else if (errorImg && source == "img") {
        this.top.imgList.setItem(target.dataset.index, errorImg);
        this.$set(this.ctrl, i, 3);
      }
      this.top &&
        this.top.$emit("error", {
          source,
          target,
          errMsg: e.detail.errMsg,
        });
    },
    _loadVideo(e) {
      this.$set(this.ctrl, e.target.dataset.i, 0);
    },
  },
};
</script>

<style>
/* 在这里引入自定义样式 */

/* 链接和图片效果 */
._a {
  display: inline;
  padding: 1.5px 0 1.5px 0;
  color: #366092;
  word-break: break-all;
}

._hover {
  text-decoration: underline;
  opacity: 0.7;
}

._img {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
}

/* #ifdef MP-WEIXIN */
:host {
  display: inline;
}

/* #endif */

/* #ifndef MP-ALIPAY || APP-PLUS */
.interlayer {
  display: inherit;
  flex-direction: inherit;
  flex-wrap: inherit;
  align-content: inherit;
  align-items: inherit;
  justify-content: inherit;
  width: 100%;
  white-space: inherit;
}

/* #endif */

._b,
._strong {
  font-weight: bold;
}

/* #ifndef MP-ALIPAY */
._blockquote,
._div,
._p,
._ol,
._ul,
._li {
  display: block;
}

/* #endif */

._code {
  font-family: monospace;
}

._del {
  text-decoration: line-through;
}

._em,
._i {
  font-style: italic;
}

._h1 {
  font-size: 2em;
}

._h2 {
  font-size: 1.5em;
}

._h3 {
  font-size: 1.17em;
}

._h5 {
  font-size: 0.83em;
}

._h6 {
  font-size: 0.67em;
}

._h1,
._h2,
._h3,
._h4,
._h5,
._h6 {
  display: block;
  font-weight: bold;
}

._image {
  display: block;
  width: 100%;
  height: 360px;
  margin-top: -360px;
  opacity: 0;
}

._ins {
  text-decoration: underline;
}

._li {
  flex: 1;
  width: 0;
}

._ol-bef {
  width: 36px;
  margin-right: 5px;
  text-align: right;
}

._ul-bef {
  display: block;
  margin: 0 12px 0 23px;
  line-height: normal;
}

._ol-bef,
._ul-bef {
  flex: none;
  user-select: none;
}

._ul-p1 {
  display: inline-block;
  width: 0.3em;
  height: 0.3em;
  overflow: hidden;
  line-height: 0.3em;
}

._ul-p2 {
  display: inline-block;
  width: 0.23em;
  height: 0.23em;
  border: 0.05em solid black;
  border-radius: 50%;
}

._q::before {
  content: '"';
}

._q::after {
  content: '"';
}

._sub {
  font-size: smaller;
  vertical-align: sub;
}

._sup {
  font-size: smaller;
  vertical-align: super;
}

/* #ifdef MP-ALIPAY || APP-PLUS || QUICKAPP-WEBVIEW */
._abbr,
._b,
._code,
._del,
._em,
._i,
._ins,
._label,
._q,
._span,
._strong,
._sub,
._sup {
  display: inline;
}

/* #endif */

/* #ifdef MP-WEIXIN || MP-QQ */
.__bdo,
.__bdi,
.__ruby,
.__rt {
  display: inline-block;
}

/* #endif */
._video {
  position: relative;
  display: inline-block;
  width: 300px;
  height: 225px;
  background-color: black;
}

._video::after {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -15px 0 0 -15px;
  content: "";
  border-color: transparent transparent transparent white;
  border-style: solid;
  border-width: 15px 0 15px 30px;
}
</style>
